#![allow(non_upper_case_globals)]

use core::ffi::c_int;
use core::ffi::c_uint;
use core::ffi::CStr;
use std::ffi::c_char;
use std::ffi::c_uchar;
use std::ffi::c_ushort;

pub type FcChar8 = c_uchar;
pub type FcChar16 = c_ushort;
pub type FcChar32 = c_uint;
pub type FcBool = c_int;

pub type FcResult = c_uint;
pub const FcResultMatch: FcResult = 0_u32;
pub const FcResultNoMatch: FcResult = 1_u32;
pub const FcResultTypeMismatch: FcResult = 2_u32;
pub const FcResultNoId: FcResult = 3_u32;
pub const FcResultOutOfMemory: FcResult = 4_u32;

pub const FcMatchPattern: FcMatchKind = 0_u32;
pub const FcMatchFont: FcMatchKind = 1_u32;
pub const FcMatchScan: FcMatchKind = 2_u32;

pub type FcMatchKind = c_uint;

pub type FcConfig = core::ffi::c_void;
pub type FcPattern = core::ffi::c_void;
pub type FcCharSet = core::ffi::c_void;

pub const FC_WEIGHT_THIN: c_int = 0;
pub const FC_WEIGHT_EXTRALIGHT: c_int = 40;
pub const FC_WEIGHT_ULTRALIGHT: c_int = FC_WEIGHT_EXTRALIGHT;
pub const FC_WEIGHT_LIGHT: c_int = 50;
pub const FC_WEIGHT_BOOK: c_int = 75;
pub const FC_WEIGHT_REGULAR: c_int = 80;
pub const FC_WEIGHT_NORMAL: c_int = FC_WEIGHT_REGULAR;
pub const FC_WEIGHT_MEDIUM: c_int = 100;
pub const FC_WEIGHT_DEMIBOLD: c_int = 180;
pub const FC_WEIGHT_SEMIBOLD: c_int = FC_WEIGHT_DEMIBOLD;
pub const FC_WEIGHT_BOLD: c_int = 200;
pub const FC_WEIGHT_EXTRABOLD: c_int = 205;
pub const FC_WEIGHT_ULTRABOLD: c_int = FC_WEIGHT_EXTRABOLD;
pub const FC_WEIGHT_BLACK: c_int = 210;
pub const FC_WEIGHT_HEAVY: c_int = FC_WEIGHT_BLACK;
pub const FC_WEIGHT_EXTRABLACK: c_int = 215;
pub const FC_WEIGHT_ULTRABLACK: c_int = FC_WEIGHT_EXTRABLACK;

pub const FC_SLANT_ROMAN: c_int = 0;
pub const FC_SLANT_ITALIC: c_int = 100;
pub const FC_SLANT_OBLIQUE: c_int = 110;

pub const FC_WIDTH_ULTRACONDENSED: c_int = 50;
pub const FC_WIDTH_EXTRACONDENSED: c_int = 63;
pub const FC_WIDTH_CONDENSED: c_int = 75;
pub const FC_WIDTH_SEMICONDENSED: c_int = 87;
pub const FC_WIDTH_NORMAL: c_int = 100;
pub const FC_WIDTH_SEMIEXPANDED: c_int = 113;
pub const FC_WIDTH_EXPANDED: c_int = 125;
pub const FC_WIDTH_EXTRAEXPANDED: c_int = 150;
pub const FC_WIDTH_ULTRAEXPANDED: c_int = 200;

pub const FC_PROPORTIONAL: c_int = 0;
pub const FC_DUAL: c_int = 90;
pub const FC_MONO: c_int = 100;
pub const FC_CHARCELL: c_int = 110;

pub const FC_RGBA_UNKNOWN: c_int = 0;
pub const FC_RGBA_RGB: c_int = 1;
pub const FC_RGBA_BGR: c_int = 2;
pub const FC_RGBA_VRGB: c_int = 3;
pub const FC_RGBA_VBGR: c_int = 4;
pub const FC_RGBA_NONE: c_int = 5;

pub const FC_HINT_NONE: c_int = 0;
pub const FC_HINT_SLIGHT: c_int = 1;
pub const FC_HINT_MEDIUM: c_int = 2;
pub const FC_HINT_FULL: c_int = 3;

pub const FC_LCD_NONE: c_int = 0;
pub const FC_LCD_DEFAULT: c_int = 1;
pub const FC_LCD_LIGHT: c_int = 2;
pub const FC_LCD_LEGACY: c_int = 3;

pub const FC_CHARSET_MAP_SIZE: c_int = 8;
pub const FC_CHARSET_DONE: u32 = u32::MAX;
pub const FC_UTF8_MAX_LEN: c_int = 6;

pub const FC_FAMILY: &CStr = c"family";
pub const FC_STYLE: &CStr = c"style";
pub const FC_SLANT: &CStr = c"slant";
pub const FC_WEIGHT: &CStr = c"weight";
pub const FC_SIZE: &CStr = c"size";
pub const FC_ASPECT: &CStr = c"aspect";
pub const FC_PIXEL_SIZE: &CStr = c"pixelsize";
pub const FC_SPACING: &CStr = c"spacing";
pub const FC_FOUNDRY: &CStr = c"foundry";
pub const FC_ANTIALIAS: &CStr = c"antialias";
pub const FC_HINTING: &CStr = c"hinting";
pub const FC_HINT_STYLE: &CStr = c"hintstyle";
pub const FC_VERTICAL_LAYOUT: &CStr = c"verticallayout";
pub const FC_AUTOHINT: &CStr = c"autohint";
pub const FC_GLOBAL_ADVANCE: &CStr = c"globaladvance";
pub const FC_WIDTH: &CStr = c"width";
pub const FC_FILE: &CStr = c"file";
pub const FC_INDEX: &CStr = c"index";
pub const FC_FT_FACE: &CStr = c"ftface";
pub const FC_RASTERIZER: &CStr = c"rasterizer";
pub const FC_OUTLINE: &CStr = c"outline";
pub const FC_SCALABLE: &CStr = c"scalable";
pub const FC_COLOR: &CStr = c"color";
pub const FC_VARIABLE: &CStr = c"variable";
pub const FC_SCALE: &CStr = c"scale";
pub const FC_SYMBOL: &CStr = c"symbol";
pub const FC_DPI: &CStr = c"dpi";
pub const FC_RGBA: &CStr = c"rgba";
pub const FC_MINSPACE: &CStr = c"minspace";
pub const FC_SOURCE: &CStr = c"source";
pub const FC_CHARSET: &CStr = c"charset";
pub const FC_LANG: &CStr = c"lang";
pub const FC_FONTVERSION: &CStr = c"fontversion";
pub const FC_FULLNAME: &CStr = c"fullname";
pub const FC_FAMILYLANG: &CStr = c"familylang";
pub const FC_STYLELANG: &CStr = c"stylelang";
pub const FC_FULLNAMELANG: &CStr = c"fullnamelang";
pub const FC_CAPABILITY: &CStr = c"capability";
pub const FC_FONTFORMAT: &CStr = c"fontformat";
pub const FC_EMBOLDEN: &CStr = c"embolden";
pub const FC_EMBEDDED_BITMAP: &CStr = c"embeddedbitmap";
pub const FC_DECORATIVE: &CStr = c"decorative";
pub const FC_LCD_FILTER: &CStr = c"lcdfilter";
pub const FC_FONT_FEATURES: &CStr = c"fontfeatures";
pub const FC_FONT_VARIATIONS: &CStr = c"fontvariations";
pub const FC_NAMELANG: &CStr = c"namelang";
pub const FC_PRGNAME: &CStr = c"prgname";
pub const FC_HASH: &CStr = c"hash";
pub const FC_POSTSCRIPT_NAME: &CStr = c"postscriptname";
pub const FC_FONT_HAS_HINT: &CStr = c"fonthashint";
pub const FC_CACHE_SUFFIX: &CStr = c".cache-";
pub const FC_DIR_CACHE_FILE: &CStr = c"fonts.cache-";
pub const FC_USER_CACHE_FILE: &CStr = c".fonts.cache-";
pub const FC_CHARWIDTH: &CStr = c"charwidth";
pub const FC_CHAR_WIDTH: &CStr = c"charwidth";
pub const FC_CHAR_HEIGHT: &CStr = c"charheight";
pub const FC_MATRIX: &CStr = c"matrix";
pub const FC_ORDER: &CStr = c"order";

#[derive(Default, Debug)]
pub struct FcFuns {
	pub fc_init: Option<unsafe extern "C" fn() -> *mut FcConfig>,
	pub fc_config_destroy: Option<unsafe extern "C" fn(*mut FcConfig)>,
	pub fc_config_substitute: Option<unsafe extern "C" fn(*mut FcConfig, *mut FcPattern, FcMatchKind) -> FcBool>,
	pub fc_default_substitute: Option<unsafe extern "C" fn(*mut FcPattern)>,
	pub fc_font_match: Option<unsafe extern "C" fn(*mut FcConfig, *mut FcPattern, *mut FcResult) -> *mut FcPattern>,
	pub fc_pattern_create: Option<unsafe extern "C" fn() -> *mut FcPattern>,
	pub fc_pattern_destroy: Option<unsafe extern "C" fn(*mut FcPattern)>,
	pub fc_pattern_add_string: Option<unsafe extern "C" fn(*mut FcPattern, *const c_char, *const FcChar8) -> FcBool>,
	pub fc_pattern_add_integer: Option<unsafe extern "C" fn(*mut FcPattern, *const c_char, c_int) -> FcBool>,
	pub fc_pattern_add_charset: Option<unsafe extern "C" fn(*mut FcPattern, *const c_char, *mut FcCharSet) -> FcBool>,
	pub fc_pattern_get_string: Option<unsafe extern "C" fn(*mut FcPattern, *const c_char, c_int, *mut *mut FcChar8) -> FcResult>,
	pub fc_pattern_get_integer: Option<unsafe extern "C" fn(*mut FcPattern, *const c_char, c_int, *mut c_int) -> FcResult>,
	pub fc_char_set_create: Option<unsafe extern "C" fn() -> *mut FcCharSet>,
	pub fc_char_set_destroy: Option<unsafe extern "C" fn(*mut FcCharSet)>,
	pub fc_char_set_add_char: Option<unsafe extern "C" fn(*mut FcCharSet, FcChar32)>,
}
impl FcFuns {
	pub unsafe fn load(lib: *mut core::ffi::c_void) -> Self {
		use super::dlsym;
		Self {
			fc_init: core::mem::transmute(dlsym(lib, b"FcInitLoadConfigAndFonts\0".as_ptr() as _)),
			fc_config_destroy: core::mem::transmute(dlsym(lib, b"FcConfigDestroy\0".as_ptr() as _)),
			fc_config_substitute: core::mem::transmute(dlsym(lib, b"FcConfigSubstitute\0".as_ptr() as _)),
			fc_default_substitute: core::mem::transmute(dlsym(lib, b"FcDefaultSubstitute\0".as_ptr() as _)),
			fc_font_match: core::mem::transmute(dlsym(lib, b"FcFontMatch\0".as_ptr() as _)),
			fc_pattern_create: core::mem::transmute(dlsym(lib, b"FcPatternCreate\0".as_ptr() as _)),
			fc_pattern_destroy: core::mem::transmute(dlsym(lib, b"FcPatternDestroy\0".as_ptr() as _)),
			fc_pattern_add_string: core::mem::transmute(dlsym(lib, b"FcPatternAddString\0".as_ptr() as _)),
			fc_pattern_add_integer: core::mem::transmute(dlsym(lib, b"FcPatternAddInteger\0".as_ptr() as _)),
			fc_pattern_add_charset: core::mem::transmute(dlsym(lib, b"FcPatternAddCharSet\0".as_ptr() as _)),
			fc_pattern_get_string: core::mem::transmute(dlsym(lib, b"FcPatternGetString\0".as_ptr() as _)),
			fc_pattern_get_integer: core::mem::transmute(dlsym(lib, b"FcPatternGetInteger\0".as_ptr() as _)),
			fc_char_set_create: core::mem::transmute(dlsym(lib, b"FcCharSetCreate\0".as_ptr() as _)),
			fc_char_set_destroy: core::mem::transmute(dlsym(lib, b"FcCharSetDestroy\0".as_ptr() as _)),
			fc_char_set_add_char: core::mem::transmute(dlsym(lib, b"FcCharSetAddChar\0".as_ptr() as _)),
		}
	}
}
